Skip to content

Fix: VS Code themes discard their own terminal.ansi* palette - #36

Open
pullapprove5[bot] wants to merge 1 commit into
masterfrom
pullapprove/pa-27-958f5d
Open

Fix: VS Code themes discard their own terminal.ansi* palette#36
pullapprove5[bot] wants to merge 1 commit into
masterfrom
pullapprove/pa-27-958f5d

Conversation

@pullapprove5

@pullapprove5 pullapprove5 Bot commented Aug 7, 2026

Copy link
Copy Markdown

What was wrong

COLOR_MAP in desktop/ui/lib/vscode-theme-resolver.ts had no entries for terminal.ansiBlackterminal.ansiBrightWhite, so a theme resolved from VS Code JSON discarded its own 16-color terminal ramp. ansiPaletteFor then found no PALETTES entry for the generated vscode-* id and substituted the generic Tomorrow Night / GitHub Light ramp. With "match VS Code theme" on, a Catppuccin user got Catppuccin chrome around another theme's terminal output — exactly the two-themes-in-one-window failure terminal-palettes.ts exists to prevent for bundled themes.

What changed

  • UiTheme gained an optional ansi?: AnsiPalette (lib/ui-themes.ts). The AnsiPalette interface moved there from components/Terminal/terminal-palettes.ts, since it is now part of a theme's shape; the values and their provenance stay in terminal-palettes.ts, which imports the type.
  • resolveVscodeTheme populates it from the sixteen terminal.ansi* keys, all-or-nothing: a partially published ramp topped up from the shared fallback would pair one theme's normals with another's brights, which is the same mismatch in miniature rather than a fix for it.
  • ansiPaletteFor now takes the theme, not an id, and prefers theme.ansi → the transcribed PALETTES[theme.id] → the shared ramp. The existing light/dark legibility nudge is unchanged and applies to whichever ramp wins.
  • Plumbing the theme object to the terminal. A VS Code-derived theme is built on the fly and never enters getAllUiThemes(), so an id alone can't find it again. applyUiTheme records the applied theme in a new one-purpose module lib/active-theme.ts, and buildXtermTheme reads it from there. That retires the el.dataset.uiTheme round-trip, which existed only to rejoin a palette to its theme and now has no readers. The module is separate from ui-themes.ts so the terminal doesn't pull in the theme catalog (and Shiki behind it).

I did not do the other half of the finding's optional suggestion (making PALETTES a required UiTheme field for bundled themes) — that's a larger reshuffle of the bundled theme table and isn't needed to fix the reported defect.

Tests

  • components/Terminal/xterm-theme.test.ts updated to the new plumbing (it drove the terminal through dataset.uiTheme), plus two new cases: a ramp carried on the active theme beats the shared fallback, and a null active theme still gets the shared ramp. Existing assertions — bundled ramps, bright≠normal, the fallback for a theme with no palette — are unchanged.
  • New lib/vscode-theme-resolver.test.ts: a detection carrying all sixteen keys yields the exact ramp; one with none, and one missing a single key, both leave ansi unset.

What I could not verify

The repo's tooling is not runnable in this sandbox and I did not run the tests. desktop/node_modules is absent and there is no network (npm ci --offline fails on an uncached tarball; the registry is unreachable), so scripts/test (tsc --noEmit + vitest) and prettier --check could not run. What I did check: every changed and added file parses cleanly under node --experimental-strip-types --check, and I hand-checked formatting against Prettier's 80-column defaults and the surrounding code. The type-level changes (the new ansiPaletteFor signature at its two call sites, the moved AnsiPalette import) are mechanical, but they are unverified by a compiler — worth a scripts/test run before merge.


Opened by a PullApprove implementation run (implement-finding v1) for the finding PA-27 — VS Code themes discard their own terminal.ansi palette*.
Merging this is what closes the finding as fixed.

A theme resolved from VS Code JSON dropped its `terminal.ansi*` colors on
the floor: `COLOR_MAP` never read them, so `ansiPaletteFor` found no entry
for the `vscode-*` id and substituted the generic Tomorrow Night / GitHub
Light ramp. Turning on "match VS Code theme" with Catppuccin therefore gave
Catppuccin chrome around another theme's terminal output — the two-themes-
in-one-window failure `terminal-palettes.ts` exists to prevent for the
bundled themes.

`UiTheme` now has an optional `ansi` ramp; `resolveVscodeTheme` fills it
from the sixteen keys VS Code themes publish, all-or-nothing so a partial
ramp can't pair one theme's normals with another's brights. The generic
ramp stays as the fallback it was meant to be.

Getting the ramp to the terminal needs the theme object, not just its id: a
VS Code-derived theme is built on the fly and is not in `getAllUiThemes()`.
`applyUiTheme` now records the applied theme in `lib/active-theme.ts` and
`buildXtermTheme` reads it there, which also retires the `data-ui-theme`
round-trip that existed only to rejoin a palette to its theme.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants